﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;

namespace GrainManage.Data.Util
{
    public sealed class Convertor
    {
        public static TEntity ConvertToEntity<TEntity>(DataRow row) where TEntity : class,new()
        {
            TEntity entity = default(TEntity);
            if (row != null)
            {
                entity = new TEntity();
                var props = typeof(TEntity).GetProperties(BindingFlags.Public | BindingFlags.Instance);
                foreach (var prop in props)
                {
                    if (row.Table.Columns.Contains(prop.Name))
                    {
                        var columnValue = row[prop.Name];
                        if (columnValue != DBNull.Value)
                        {
                            prop.SetValue(entity, columnValue, null);
                        }
                    }
                }
            }
            return entity;
        }

        public static List<TEntity> ConvertToEntity<TEntity>(DataTable table) where TEntity : class,new()
        {
            List<TEntity> entityList = default(List<TEntity>);
            if (table != null && table.Rows.Count > 0)
            {
                entityList = new List<TEntity>(table.Rows.Count);
                var props = typeof(TEntity).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                foreach (DataRow row in table.Rows)
                {
                    TEntity entity = new TEntity();
                    //var entity = Activator.CreateInstance<TEntity>();
                    foreach (var prop in props)
                    {
                        if (table.Columns.Contains(prop.Name))
                        {
                            var columnValue = row[prop.Name];
                            if (columnValue != DBNull.Value)
                            {
                                prop.SetValue(entity, columnValue, null);
                            }
                        }
                    }
                    entityList.Add(entity);
                }
            }
            return entityList;
        }

        public static TResultModel CopyTo<TResultModel, TOriginalModel>(TOriginalModel original)
            where TResultModel : class,new()
            where TOriginalModel : class,new()
        {
            var originalModelType = typeof(TOriginalModel);
            var resultModelProperties = typeof(TResultModel).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            var result = new TResultModel();
            foreach (var resultProperty in resultModelProperties)
            {
                var originalProperty = originalModelType.GetProperty(resultProperty.Name, BindingFlags.Public | BindingFlags.Instance);
                if (originalProperty != null && resultProperty.PropertyType == originalProperty.PropertyType)
                {
                    object value = originalProperty.GetValue(original, null);
                    resultProperty.SetValue(result, value, null);
                }
            }
            return result;
        }

        public static List<TResultModel> CopyTo<TResultModel, TOriginalModel>(List<TOriginalModel> originalModels)
            where TResultModel : class,new()
            where TOriginalModel : class,new()
        {
            var results = new List<TResultModel>(originalModels.Count);
            var originalModelType = typeof(TOriginalModel);
            var resultModelProperties = typeof(TResultModel).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
            foreach (var original in originalModels)
            {
                var result = new TResultModel();
                foreach (var resultProperty in resultModelProperties)
                {
                    var originalProperty = originalModelType.GetProperty(resultProperty.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                    if (originalProperty != null && resultProperty.PropertyType == originalProperty.PropertyType)
                    {
                        object value = originalProperty.GetValue(original, null);
                        resultProperty.SetValue(result, value, null);
                    }
                }
                results.Add(result);
            }
            return results;
        }
    }
}
